GNUPLOT *openGnuplot(const char *gnuplotpath)
int writeGnuplot(GNUPLOT *gp, const char *command)
int readErrorGnuplot(GNUPLOT *gp, char *buf, size_t n)
int readGnuplot(GNUPLOT *gp, char *buf, size_t n)
GPCurve *readCurveGnuplot(GNUPLOT *gp)
int readCurveHeadGnuplot(GNUPLOT *gp, int *curveno, int *npts)
int readCurve2Gnuplot(GNUPLOT *gp, char *range, float *x, float *y, int npts)
int readCurve3Gnuplot(GNUPLOT *gp, char *range, float *x, float *y, float *z,int npts)
int closeGnuplot(GNUPLOT *gp, int quitflag)
The gnuplotio library allows an application to run the gnuplot(1L) plotting package interactively via UNIX pipes. gnuplot(1L) is spawned using a variant of popen(3), called popen_ioe(3L), which opens the gnuplot process for writing on stdin, and reading on both stdout and stderr.
General Interactive Use
To run
gnuplot
interactively, but under the control of a program, only
openGnuplot(),
writeGnuplot(),
readGnuplot(),
closeGnuplot(),
and perhaps
readErrorGnuplot()
need ever be called. The output will appear graphically on whatever output
device the application chooses to set.
Expression Evaluator
An application can turn
gnuplot(1L)
into a poor man's expression evaluator by setting the terminal type to
``table''. Then, instead of plotting a graph of the expression in the
``plot
expr''
and ``splot
expr''
commands,
gnuplot(1L)
writes the evaluated X, Y (and in the case of splot, Z) values in an
ASCII table on
its stdout. The application can retrieve the samples and do whatever
further processing it wants to, eg. compute the Fourier Transform of
an analytic function that the user typed in. The sampling rate (interval)
can be controlled by specifying the number of samples and the evaluation
interval. For example, the following code fragment evaluates the expression
at intervals of 200 samples/10 sec = 20 samples/sec (or a sampling rate of
50 msec).
gp = openGnuplot(""); writeGnuplot(gp,"set term table"); writeGnuplot(gp,"set samples 200"); writeGnuplot(gp,"plot [x=0:9] exp(-.02*x)*sin(x)"); gc = readCurve(gp); closeGnuplot(gp,0);
Thus, for a small additional programming effort, a programmer can leverage off the development of gnuplot and add full-fledged expression evaluation capability to his or her application without having to know _anything_ about parsing and lexical analysis!
Routine Descriptions
openGnuplot()
opens a connection to the
gnuplot
program named in
gnuplotpath.
If it is a NULL pointer or a NULL string,
openGnuplot()
will search the user's $PATH (see
environ(5))
for the generic program ``gnuplot''.
openGnuplot()
will return a GNUPLOT handle after
gnuplot
is located, executed, and
communications are established; otherwise NULL is returned. The handle is
unique to that communication channel and must be passed to other
gnuplotio
routines. This allows an application to open multiple, independent connections
to
gnuplot
if it wants to.
writeGnuplot() issues command to gnuplot. (See gnuplot(1L) as well as the on-line help for more information on the syntax and meaing on gnuplot commands.) The command string will be newline-terminated if it doesn't end with a newline already. (Gnuplot needs a newline to know when to begin interpreting the command, as it reads its input using line buffering.) -1 is returned if gp is not a properly initialized GNUPLOT handle or the command pointer is NULL. Otherwise 1 is returned, indicating success, even though there is no absolute guarantee that gnuplot got and understood the command.
There are several ways to retreive information back from gnuplot: readGnuplot(), readCurveGnuplot(), readCurveHeadGnuplot(), readCurve2Gnuplot(), readCurve3Gnuplot(), readErrorGnuplot(). readGnuplot() reads one line of output from gnuplot and copies the characters, without interpretation, into buf, limited to a maximum of n characters. readGnuplot() returns 1 upon successful read [should return the number of characters actually copied into buf on success], and -1 if any input parameters were invalid. Use this read to get status-type information from gnuplot, such as the response to a ``show'' command. readCurveGnuplot() completely processes the returned data after a ``plot expr'' or a ``splot expr'' command has been written with writeGnuplot(). A pointer to a GPCurve struct is returned on success, which contains npts, the number pf points returned, float arrays x[] and y[] (allocated by malloc(3) to npts). range[] is a character flag array which tells whether each point is inrange, (inside the plot bounds), outrange (outside of the plot bounds but still defined), or undefined (eg. in the case of infinities occurring in the interval over which the expression was evaluated). The flag is_2d will be TRUE if the data is a 2D line plot (``plot'' command) and the z pointer will be NULL. If the curve represents the output from a 3D surface plot (``splot'' command), is_2d will be FALSE and z[] will be allocated just like x[] and y[].
typedef struct { unsigned npts; /* number of points */ int is_2d; /* True: only x,y are valid; z=NULL */ int curveno; /* Curve id number */ float *x; /* x[npts] */ float *y; /* y[npts] */ float *z; /* z[npts] */ char *range; /* range[npts]: 'i' inrange, 'o' outrange, 'u' undefined */ } GPCurve;
If the application writes a plot command requesting more than one curve, eg. ``plot sin(x),x*cos(x),bessj0(x)'' then the application should call readCurveGnuplot() as many times as necessary to retrieve all the curve data. The curveno field will be set with curve identifier number (Note: unique only to that specific plot command). NULL is returned if any input parameters are invalid or readCurveGnuplot() if can't malloc(3) all the space it needs.
closeGnuplot() shuts down a connection to gnuplot. If quitflag is non-zero, a ``quit'' command will be sent first to gnuplot to allow for a graceful exit. Then the pipe connections will be closed. A 0 is returned if pclose_ioe(3L) fails and a 1 for successful close.
The routines readCurveHeadGnuplot(), readCurve2Gnuplot(), and readCurve3Gnuplot() provide the application with more control by doing the job of readCurveGnuplot() in pieces. For example, readCurveHeadGnuplot() returns only the curve id number and number of points into curveno and npts, respectively. The application can then malloc(3) its own arrays and have readCurve2Gnuplot() fill the range, x, y arrays, in the case of 2D data. For 3D data, readCurve3Gnuplot() will fill the range, x, y, z arrays. In both routines, if the application doesn't care about the range information, pass a NULL pointer for range.
Error Handling
If
gnuplot
detects a syntax or other error on the input command, it will
write an error message on its stderr, which the application can fetch with
readErrorGnuplot().
readErrorGnuplot()
uses
select(2)
so it will not block if there is no error message to read. The message, if any,
is copied into
buf
and the number of characters copied is returned (0 for no message).
Due to latencies involved with stdout buffering, an error may not be detected
immediately after an erroneous command is issued to
gnuplot.
For example, in the sequence
writeGnuplot(gp, "plotte nofunc(a)"); if(readErrorGnuplot(gp, buf, n) > 0) { /* Error! */ };
readErrorGnuplot() may not report an error. But it will be reported by the next call to readErrorGnuplot().